export default class TextNode {
    constructor() {
        this.lines = []
        this.font = ''
        this.dirty = true
        this.width = 0
        this.height = 0
    }
    compute(ctx, text, options) {
        if (!this.dirty) return
        const arr = typeof (text) === 'string' ? text.split(/\n/) : [],
            reg = /[,，。\.\?？！!'"”“‘’、s\s》>`·]/,
            lines = []

        this.font = [options.fontStyle,
        options.fontVariant,
        options.fontWeight,
        options.fontSize + 'px/' + options.lineHeight + 'px',
        options.fontFamily].join(' ')
        this.width = options.width - options.padding[3] - options.padding[1] - options.border[0]
        this.height = 0

        ctx.save()
        ctx.font = this.font
        for (let i = 0, len = arr.length, info = null, lineIndex = 0; i < len; i++) {
            let p = arr[i]
            info = ctx.measureText(p)
            if (info.width > this.width) {
                let n = Math.floor(this.width / options.fontSize), len = p.length
                for (let j = n; j < len; j++) {
                    info = ctx.measureText(p.slice(0, j))
                    if (info.width > this.width) {
                        let sIndex = reg.test(p.charAt(j - 1)) ? j : j - 1
                        lines[lineIndex++] = p.slice(0, sIndex)
                        p = p.slice(sIndex)
                        len = p.length
                        j = len > n ? n : len
                    }
                }
            }
            lines[lineIndex++] = p
        }
        this.lines = lines
        this.height = options.lineHeight * lines.length
        ctx.restore()
        this.dirty = false
    }
    render(ctx, options) {
        if (!ctx) return
        ctx.save()
        //字体
        ctx.font = this.font
        //垂直对齐固定值
        ctx.textBaseline = 'top'
        //阴影
        if (options.textShadow.length === 4) {
            ctx.shadowColor = options.textShadow[0]
            ctx.shadowOffsetX = options.textShadow[1]
            ctx.shadowOffsetY = options.textShadow[2]
            ctx.shadowBlur = options.textShadow[3]
        }
        //水平对齐
        ctx.textAlign = options.textAlign
        ctx.color = options.color
        //文字对齐方式对文字x坐标的影响
        let x = 0
        if (options.textAlign === 'left') x = -options.width / 2 + options.padding[3]
        if (options.textAlign === 'right') x = options.width / 2 - options.padding[1]
        let height = options.height - options.padding[0] - options.padding[2] - options.border[0]
        this.lines.forEach((txt, k) => {
            ctx.fillText(txt, x + options.border[0]/2, k * options.lineHeight - height / 2 + (options.lineHeight - options.fontSize) / 2)
        })
        //文字边框和渲染边框部分
        if (options.textBorder[0] > 0 && options.textBorder[1]) {
            ctx.lineWidth = options.textBorder[0]
            ctx.strokeStyle = options.textBorder[1]
            this.lines.forEach((t, k) => {
                ctx.strokeText(t, x, k * options.lineHeight - height / 2 + (options.lineHeight - options.fontSize) / 2)
            })
        }
        ctx.restore()
    }
}